//package com.easyim.imserver.handler.message;
//
//import com.easyim.common.message.Immessage;
//import com.easyim.imserver.service.ITokenService;
//import io.netty.channel.Channel;
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.beans.factory.annotation.Qualifier;
//import org.springframework.beans.factory.annotation.Value;
//import org.springframework.stereotype.Component;
//
//import java.util.Map;
//import java.util.concurrent.ConcurrentHashMap;
//
//import static com.easyim.imserver.constant.CacheKey.*;
//
//@Slf4j
//@Component
//public class CmdMsgHandler implements Handler{
//
//    @Autowired
//    private ITokenService tokenService;
//
//    @Autowired
//    @Qualifier("channelMap")
//    Map<String, Map<String, Channel>>  localSession;
//
//    @Override public String dealType() {
//        return CMD_MSG_HANDLER_KEY;
//    }
//
//    @Value("${com.easyim.run.model.clusterable}")
//    private Boolean cluster = false;
//
//    @Override
//    public void handlerMsg(Channel channel,
//            Immessage.ImMessage imMessage) {
//        dealCmdMsg(channel, imMessage);
//    }
//
//    private void dealCmdMsg(Channel channel,
//            Immessage.ImMessage imMessage) {
//        //检查命令消息
//        Immessage.CmdMessage cmdMessage = imMessage.getCmdMessage();
//        Immessage.CmdMessage.CommandType command = imMessage.getCmdMessage().getCommand();
//        switch (command) {
//            case CONNECT -> {
//                //校验token
//                log.info("user:{} use tcp connect.. start auth!", cmdMessage.getUsername());
//                //todo 做认证逻辑 这种认证 只需要实现某个类的接口即可 这里其实可以直接设置个http的客户端 直接调用
//                Boolean authSuccess = tokenService.checkToken(null);
//                // 如果认证成功了 就直接连
//                if (authSuccess) {
//                    //一个端只能登陆一个账号 如果当前端判断已经有了会话。那么就要发送踢下去命令
//                    //把会话加入缓存 加入到redis里面
//                    String device = cmdMessage.getDevice();
//                    String username = cmdMessage.getUsername();
//                    channel.attr(USERNAME).set(username);
//                    channel.attr(DEVICE).set(device);
//                    channel.attr(AUTHENTICATED).set(Boolean.TRUE);
//                    //channelinfo放进去redis如果是本机的 那么自己投递 如果不是的话 那么就找其他节点投递
//                    //把会话 放进缓存中
//                    if(cluster){
//                        //集群模式存储会话redis 否则直接存在本地里面就可以了
//                    }
//                    //把当前会话缓存 到时候用来发消息
//                    if(localSession.containsKey(username)){
//                        //说明其他端可能在这个设备有登陆了
//                        Map<String, Channel> devicecChannelMap = localSession.get(username);
//                        if(devicecChannelMap.containsKey(device)){
//                            //todo 这个设备 在当前端 登陆了 所以发个cmd 告诉之前旧的channel被人踢了
//                            //集群版这个要检查redis的
//                        }
//                        devicecChannelMap.put(device, channel);
//                    }else {
//                        //先把会话列表推给客户端，然后把所有消息给客户端。这样子 才会稳妥。直到没有消息了 然后才认为他连接成功了
//                        //给会话的时候 要把最后一条消息id也给了。还有未读条数.. 只有用户去拉取未读消息。查最接近的那十个消息。查到了给客户端就完事了
//                        //客户端的会话列表 需要加锁 锁住 然后就算有新消息到了 也只是拉完会话列表 进行一个重排序
//
//                        //这里给会话的原因只有一个告诉客户端 你还有多少会话 多少会话里面有消息 你需要拉取 你不拉取是客户端的事。查询客户上一次读取到哪里了。把分数大于上次读取到的会话全取出来。
//                        //本地数据库。最新的消息id拉取会话列表. 这个前端来传需要把自己的消息id传过来. 第一时间。在登陆成功后 立马拉取会话列表。把自己数据库的消息id传过来 然后再建立长链接 如果不传的话 就查询所有会话
//                        //之前设计的服务器端保存每个端读取到哪里了 方案的不合适之处在于 刚登陆 有很多未读消息 但是有一条新消息下发 游标会进行大幅度的跳跃。导致消息失灵了
//                        Map<String, Channel> devicecChannelMap = new ConcurrentHashMap<>();
//                        devicecChannelMap.put(device, channel);
//                        localSession.put(username, devicecChannelMap);
//                    }
//                } else {
//                    //todo 发送消息告诉客户端鉴权失败
//                }
//            }
//            case DISCONNECT -> {
//                log.info("user:{} disconnect tcp connect.. start auth!", cmdMessage.getUsername());
//                channel.close();
//            }
//            case PING -> {
//                //返回一个PONG信息 持续这个会话
//                //心跳 对所有的session进行检测 如果n次没有心跳 那么认为它挂了 count 以及时间 1s 一个心跳 次数10的话 就是断了十秒才知道
//
//                //断了多少秒就知道了  两个人 如果同心宝藏。。同心宝藏 十颗星 刷够了 就可以一起开启宝藏
//
//                //慢节奏。游戏 也就说 延时队列 发给自己的信..延迟队列.. 慢递邮局. 如何找到好友 好友只能通过系统推送...
//                //系统如何推送...
//            }
//        }
//    }
//
//}
